package com.quectel.cms.controller.device;


import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.quectel.business.dms.device.CommandBusiness;
import com.quectel.cms.constants.CmsRedisCacheConstants;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.cms.vo.device.*;
import com.quectel.constant.core.ResourceGroupCodeConstants;
import com.quectel.constant.core.device.DeviceDynamicAttrConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.core.module.alarm.dto.AlarmRuleConditionDto;
import com.quectel.core.module.alarm.dto.AlarmRuleDeviceConditionDto;
import com.quectel.core.module.alarm.dto.AlarmRuleDto;
import com.quectel.core.module.alarm.service.AlarmRuleDeviceConditionService;
import com.quectel.core.module.alarm.service.AlarmRuleService;
import com.quectel.core.module.device.dto.DeviceColumnDto;
import com.quectel.core.module.device.dto.DeviceDto;
import com.quectel.core.module.device.dto.DeviceDynamicAttrDto;
import com.quectel.core.module.device.dto.mongo.MongoDeviceAlarmLogDto;
import com.quectel.core.module.device.dto.mongo.MongoDeviceCommandLogDto;
import com.quectel.core.module.device.dto.mongo.MongoDeviceDataLogDto;
import com.quectel.core.module.device.service.*;
import com.quectel.core.module.device.service.mongo.MongoDeviceService;
import com.quectel.util.common.*;
import com.quectel.util.kit.PageFetchKit;
import com.quectel.util.redis.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * @author rananxin
 * @date 2021-10-29 13:49:59
 */
@RestController
@RequestMapping("device")
@Tag(name = "DeviceController", description = "设备相关api")
public class DeviceController extends BaseController {

    @DubboReference
    private DeviceService deviceService;
    @DubboReference
    private DeviceCategoryService deviceCategoryService;
    @DubboReference
    private DeviceTypeService deviceTypeService;
    @DubboReference
    private DeviceColumnService deviceColumnService;
    @DubboReference
    private MongoDeviceService mongoDeviceService;
    @DubboReference
    private DeviceCommandTemplateService deviceCommandTemplateService;
    @DubboReference
    private DeviceDynamicAttrService deviceDynamicAttrService;
    @DubboReference
    private AlarmRuleDeviceConditionService alarmRuleDeviceConditionService;
    @DubboReference
    private AlarmRuleService alarmRuleService;

    @Autowired
    private CommandBusiness commandBusiness;

    private static final String MSG_NO_GENERATE = "MSG_NO_GENERATE:";

    // 设备上下级关联操作，租户锁
    public static final String DEVICE_LINK_OPERATE_LOCK =
            CmsRedisCacheConstants.PROJECT_NAME + "DEVICE_LINK_OPERATE_LOCK:";

    @GetMapping("queryPatrolDevices")
    @Operation(summary = "查询巡检分组设备")
    public Response<List<DeviceDto>> queryPatrolDevices(
            @RequestParam(required = false) Long villageId
    ) {
        List<DeviceDto> result = new ArrayList<>();

        Map<String, Object> params = Request.parseParams(httpServletRequest);


        super.fillAuthorityData(params);
        super.fillResourceGroupCode(params, ResourceGroupCodeConstants.PATROL_DEVICE_GROUP);


        return Response.<List<DeviceDto>>ok().wrap(PageFetchKit.fetchAll(req -> deviceService.queryList(req), params, 500));
    }

    /**
     * 设备上下级关联
     *
     * @return
     */
    @PostMapping("linkOrUnlinkParent")
    @RequirePermissions(values = "device:edit")
    @Operation(summary = "设备上下级关联")
    public Response linkOrUnlinkParent(@RequestBody @Validated DeviceLinkReq deviceLinkReq) {
        if (!Objects.isNull(deviceLinkReq.getTargetDeviceId())
                && deviceLinkReq.getCurrentDeviceId().equals(deviceLinkReq.getTargetDeviceId())) {
            return Response.error("关联设备不能为自身");
        }
        DeviceDto currentDto = deviceService.selectCacheById(deviceLinkReq.getCurrentDeviceId());
        if (Objects.isNull(currentDto)) {
            return Response.error("操作设备不存在");
        }
        Lock spinLock = RedisUtils.getSpinLock(DEVICE_LINK_OPERATE_LOCK
                + Objects.requireNonNull(SessionHolder.getSysUser()).getTenantId());
        spinLock.lock();
        try {
            if (!Objects.isNull(deviceLinkReq.getTargetDeviceId())) {
                boolean isExist = deviceService.queryByParent(currentDto.getId()).parallelStream()
                        .map(DeviceDto::getId)
                        .anyMatch(o -> o.equals(deviceLinkReq.getTargetDeviceId()));
                if (isExist) {
                    return Response.error("不能关联当前设备的子设备");
                }
                DeviceDto newlyDto = new DeviceDto();
                newlyDto.setId(currentDto.getId());
                newlyDto.setParentId(deviceLinkReq.getTargetDeviceId());
                deviceService.updateById(newlyDto);
            } else {
                currentDto.setParentId(SystemConstants.TREE_DEFAULT_PARENT_ID);
                deviceService.updateAllColumnById(currentDto);
            }
            return Response.ok();
        } catch (Exception e) {
            logger.warn("设备上下级关联操作异常", e);
        } finally {
            spinLock.unlock();
        }
        return Response.error("操作异常");
    }

    /**
     * 属性设置
     *
     * @param attrSpecialSetVo
     * @return
     */
    @PostMapping("specialSet")
    @RequirePermissions(values = "device:edit")
    @Operation(summary = "设备属性设置")
    public Response<Object> specialSet(@RequestBody @Validated DeviceAttrSpecialSetVo attrSpecialSetVo) {

        Response<Object> resp = checkExpandAttr(attrSpecialSetVo.getDeviceCategoryId(), attrSpecialSetVo.getParams());
        if (!resp.isSuccess()) {
            return resp;
        }

        for (Long id : attrSpecialSetVo.getIds()) {
            DeviceDto oldDto = deviceService.selectById(id);
            if (oldDto == null) {
                continue;
            }
            String dbExt = oldDto.getExtraAttr();
            Map<String, Object> dbJson = dbExt == null ? new HashMap<>() : JacksonUtils.parse(dbExt, new TypeReference<HashMap<String, Object>>() {
            });
            for (Map.Entry<String, Object> entry : attrSpecialSetVo.getParams().entrySet()) {
                if (entry.getValue() != null) {
                    if (entry.getValue() instanceof String) {
                        if (StringUtils.isNotBlank((String) entry.getValue())) {
                            dbJson.put(entry.getKey(), entry.getValue());
                        } else {
                            dbJson.remove(entry.getKey());
                        }
                    } else {
                        dbJson.put(entry.getKey(), entry.getValue());
                    }
                } else {
                    dbJson.remove(entry.getKey());
                }
            }

            DeviceDto deviceDto = new DeviceDto();
            deviceDto.setId(id);
            deviceDto.setExtraAttr(JacksonUtils.toJsonString(dbJson));
            deviceService.updateById(deviceDto);
        }
        return Response.ok();
    }

    private Response<Object> checkExpandAttr(Long deviceCategoryId, Map<String, Object> params) {
        Map<String, Object> queryAttrMap = new HashMap<>();
        queryAttrMap.put(LambdaUtil.getFieldName(DeviceDynamicAttrDto::getDeviceCategoryId), String.valueOf(deviceCategoryId));

        List<DeviceDynamicAttrDto> deviceDynamicAttrDtos = deviceDynamicAttrService.queryList(queryAttrMap);

        // 校验
        for (DeviceDynamicAttrDto attrDto : deviceDynamicAttrDtos) {
            Object o = params.get(attrDto.getAttr());

            if (SystemConstants.YES.equals(attrDto.getRequired())) {
                if (o == null || (o instanceof String && StringUtils.isBlank((String) o))) {
                    return Response.error(attrDto.getLabel() + "必传");
                }
            }

            if (o != null) {
                if (DeviceDynamicAttrConstants.FieldTypeEnum.NUMBER.getType().equals(attrDto.getFieldType())) {
                    if (!(o instanceof Number)) {
                        if (!(o instanceof String) || !NumberUtil.isNumber((String) o)) {
                            return Response.error(attrDto.getLabel() + "只能为数字");
                        }
                    }
                }
                if (DeviceDynamicAttrConstants.FieldTypeEnum.TEXT.getType().equals(attrDto.getFieldType())) {
                    if (attrDto.getTextLimit() != null) {
                        if (String.valueOf(o).length() > attrDto.getTextLimit()) {
                            return Response.error(attrDto.getLabel() + "超过最大字数限制");
                        }
                    }
                }

                if (DeviceDynamicAttrConstants.FieldTypeEnum.JSON.getType().equals(attrDto.getFieldType())) {
                    try {
                        if (!(o instanceof String)) {
                            throw new RuntimeException("Device dynamic attr json check warn.");
                        }
                        JacksonUtils.parse((String) o);
                    } catch (Exception e) {
                        return Response.error(attrDto.getLabel() + "JSON校验失败");
                    }
                }
            }
        }
        return Response.ok();
    }

    @GetMapping("queryMonitors")
    @Operation(summary = "查询监控设备")
    public Response<List<DeviceDto>> queryMonitor(
            @RequestParam(required = false) Long villageId
    ) {

        Map<String, Object> params = Request.parseParams(httpServletRequest);


        super.fillAuthorityData(params);
        super.fillResourceGroupCode(params, ResourceGroupCodeConstants.MONITORS_GROUP);


        return Response.<List<DeviceDto>>ok().wrap(PageFetchKit.fetchAll(req -> deviceService.queryList(req), params, 500));
    }


    @GetMapping("queryAll")
    @Operation(summary = "查询设备")
    public Response<List<DeviceDto>> queryAll() {
        Map<String, Object> params = Request.parseParams(httpServletRequest);
        super.fillAuthorityData(params);
        return Response.<List<DeviceDto>>ok().wrap(PageFetchKit.fetchAll(req -> deviceService.queryList(req), params, 500));
    }

    @GetMapping("commandLog")
    @RequirePermissions(values = "device:list")
    @Operation(summary = "查询指令日志列表")
    public Response<Page<MongoDeviceCommandLogDto>> commandLog(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        Long deviceId = request.getLong("deviceId");
        DeviceDto deviceDto = deviceService.selectById(deviceId);
        if (deviceDto == null) {
            return Response.error("null device");
        }

        int total = mongoDeviceService.queryDeviceCommandLogTotal(request.getParams());
        List<MongoDeviceCommandLogDto> mongoDeviceCommandLogDtos = new ArrayList<>();
        if (total > 0) {
            mongoDeviceCommandLogDtos = mongoDeviceService.queryDeviceCommandLog(request.getParams());
        }
        Page<MongoDeviceCommandLogDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, mongoDeviceCommandLogDtos);
        return Response.<Page<MongoDeviceCommandLogDto>>ok().wrap(page);
    }

    @PostMapping("sendCommand")
    @RequirePermissions(values = "device:edit")
    @Operation(summary = "发送指令")
    public Response<Object> sendCommand(@RequestBody DeviceSendCommandVo commandVo) {
        try {
            commandBusiness.send(commandVo.getDeviceId(), commandVo.getCommandTemplateId(), commandVo.getCommandContent()
                    , MongoDeviceCommandLogDto.OperatorTypeEnum.ADMIN, SessionHolder.getSysUserId());
            return Response.ok();
        } catch (Exception e) {
        }

        return Response.error("该设备暂不支持");
    }

    @GetMapping("alarmLog")
    @RequirePermissions(values = "device:list")
    @Operation(summary = "查询告警日志列表")
    public Response<Page<MongoDeviceAlarmLogDto>> alarmLog(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        Long deviceId = request.getLong("deviceId");
        DeviceDto deviceDto = deviceService.selectById(deviceId);
        if (deviceDto == null) {
            return Response.error("null device");
        }

        int total = mongoDeviceService.queryDeviceAlarmLogTotal(request.getParams());
        List<MongoDeviceAlarmLogDto> mongoDeviceAlarmLogDtos = new ArrayList<>();
        if (total > 0) {
            mongoDeviceAlarmLogDtos = mongoDeviceService.queryDeviceAlarmLog(request.getParams());
        }
        Page<MongoDeviceAlarmLogDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, mongoDeviceAlarmLogDtos);
        return Response.<Page<MongoDeviceAlarmLogDto>>ok().wrap(page);
    }

    @GetMapping("dataLog")
    @RequirePermissions(values = "device:list")
    @Operation(summary = "查询上报日志列表")
    public Response<Page<MongoDeviceDataLogDto>> dataLog(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        Long deviceId = request.getLong("deviceId");
        DeviceDto deviceDto = deviceService.selectById(deviceId);
        if (deviceDto == null) {
            return Response.error("null device");
        }


        int total = mongoDeviceService.queryReportDataTotal(request.getParams());
        List<MongoDeviceDataLogDto> mongoDeviceDataLogDtos = new ArrayList<>();
        if (total > 0) {
            mongoDeviceDataLogDtos = mongoDeviceService.queryReportData(request.getParams());
        }

        Page<MongoDeviceDataLogDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, mongoDeviceDataLogDtos);

        return Response.<Page<MongoDeviceDataLogDto>>ok().wrap(page);
    }

    /**
     * 模糊搜索
     */
    @GetMapping("searchRemote")
    @Operation(summary = "根据条件模糊搜索")
    public Response<List<HashMap<String, String>>> searchRemote(@RequestParam String queryString,
                                                                @RequestParam(required = false) String typeName) {

        Map<String, Object> params = new HashMap<>();
        params.put("queryString", queryString);
        super.fillAuthorityData(params);
        //查询列表数据
        List<DeviceDto> list = PageFetchKit.fetchAll(req -> deviceService.queryList(req), params, 500);
        if (StringUtils.isEmpty(typeName)) {
            return Response.<List<HashMap<String, String>>>ok().wrap(list.stream().map(v -> {
                return new HashMap<String, String>() {
                    {
                        put("key", v.getId() + "");
                        put("value", v.getImei());
                    }
                };
            }).collect(Collectors.toList()));
        } else {
            return Response.<List<HashMap<String, String>>>ok().wrap(list.stream().map(v -> {
                return new HashMap<String, String>() {
                    {
                        put("key", v.getId() + "");
                        put("value", v.getName());
                    }
                };
            }).collect(Collectors.toList()));
        }

    }

    @GetMapping("treeList")
    @RequirePermissions(values = "device:list")
    @Operation(summary = "树形分页列表")
    public Response<Page<DeviceTreeVo>> treeList(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest))
                .like(LambdaUtil.getFieldName(DeviceDto::getName));

        super.fillAuthorityData(request.getParams());
        int total = deviceService.queryTreeTotal(request.getParams());

        List<DeviceDto> list = null;
        if (total > 0) {
            list = deviceService.queryTreeList(request.getParams());
        } else {
            list = new ArrayList<>();
        }
        Page<DeviceTreeVo> page = new Page<>(request.getPageNo(), request.getPageSize()
                , total, treeBuilder(list, SystemConstants.TREE_DEFAULT_PARENT_ID));
        return Response.<Page<DeviceTreeVo>>ok().wrap(page);
    }

    private List<DeviceTreeVo> treeBuilder(List<DeviceDto> deviceDtos, Long rootId) {
        List<DeviceTreeVo> resp = new ArrayList<>();

        List<DeviceTreeVo> deviceTreeVoList = CopyUtils.copyList(deviceDtos, DeviceTreeVo.class);
        for (DeviceTreeVo c1 : deviceTreeVoList) {
            if (Objects.equals(rootId, c1.getParentId())) {
                resp.add(c1);
            }
            for (DeviceTreeVo c2 : deviceTreeVoList) {
                if (Objects.equals(c2.getParentId(), c1.getId())) {
                    if (c1.getChildren() == null) {
                        c1.setChildren(new ArrayList<>());
                    }
                    c1.getChildren().add(c2);
                }
            }
        }
        return resp;
    }

    /**
     * 列表
     */
    @GetMapping("list")
    @RequirePermissions(values = "device:list")
    @Operation(summary = "设备的分页查询列表")
    public Response<Page<DeviceDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest))
                .like(LambdaUtil.getFieldName(DeviceDto::getName));

        super.fillAuthorityData(request.getParams());
        int total = deviceService.queryTotal(request.getParams());

        List<DeviceDto> list = null;
        if (total > 0) {
            list = deviceService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Page<DeviceDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<DeviceDto>>ok().wrap(page);
    }


    /**
     * 信息
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "device:info")
    @Operation(summary = "查询单条设备记录")
    public Response<DeviceDto> info(@PathVariable("id") Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (deviceService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        DeviceDto deviceDto = deviceService.selectById(id);
        DeviceInfoVo deviceInfoVo = CopyUtils.copyObj(deviceDto, DeviceInfoVo.class);

        // 最新物模型数据
        JsonNode dataJson = JacksonUtils.parse(StringUtils.isNotBlank(deviceDto.getLastData()) && JSONUtil.isJsonObj(deviceDto.getLastData()) ? deviceDto.getLastData() : "{}", JsonNode.class);
        List<DeviceColumnDto> deviceColumnDtos = deviceColumnService.selectByDeviceTypeId(deviceDto.getDeviceTypeId());
        List<DeviceInfoVo.DataInfoCls> lastData = deviceColumnDtos.stream().map(o -> {
            DeviceInfoVo.DataInfoCls dataInfo = new DeviceInfoVo.DataInfoCls();
            dataInfo.setKey(o.getEntityName());
            dataInfo.setKeyCnName(o.getCnName());
            dataInfo.setUnit(o.getUnit());

            JsonNode columnValueNode = dataJson.get(o.getEntityName());
            if (columnValueNode != null) {
                String v = columnValueNode.asText();
                if (DeviceColumnDto.FieldTypeEnum.ENUM.getType().equals(o.getFieldType())) {
                    if (StringUtils.isNotBlank(o.getFieldDictJson())) {
                        JsonNode dictJson = JacksonUtils.parse(o.getFieldDictJson(), JsonNode.class);
                        String realValue = dictJson.get(v).asText();
                        dataInfo.setRealValue(realValue);
                    }
                } else {
                    dataInfo.setRealValue(v);
                }
            }


            return dataInfo;
        }).collect(Collectors.toList());
        deviceInfoVo.setLastDataInfo(lastData);

        // 个性属性数据
        JsonNode attr = JacksonUtils.parse(StringUtils.isNotBlank(deviceDto.getExtraAttr()) && JSONUtil.isJsonObj(deviceDto.getExtraAttr()) ? deviceDto.getExtraAttr() : "{}", JsonNode.class);
        Map<String, Object> queryAttrMap = new HashMap<>();
        queryAttrMap.put(LambdaUtil.getFieldName(DeviceDynamicAttrDto::getDeviceCategoryId), deviceDto.getDeviceCategoryId());
        List<DeviceDynamicAttrDto> deviceDynamicAttrDtos = deviceDynamicAttrService.queryList(queryAttrMap);
        List<DeviceInfoVo.DynamicAttrInfoCls> attrInfo = deviceDynamicAttrDtos.parallelStream().map(o -> {
            DeviceInfoVo.DynamicAttrInfoCls attrItem = new DeviceInfoVo.DynamicAttrInfoCls();
            attrItem.setLabel(o.getLabel());
            attrItem.setAttr(o.getAttr());
            attrItem.setUnit(o.getUnit());

            JsonNode attrValueNode = attr.get(o.getAttr());
            if (attrValueNode != null) {
                String v = SystemConstants.NULL_STR.equals(attrValueNode.asText()) ? "" : attrValueNode.asText();
                if (DeviceDynamicAttrConstants.FieldTypeEnum.ENUM.getType().equals(o.getFieldType())) {
                    if (StringUtils.isNotBlank(o.getFieldDictJson())) {
                        JsonNode dictJson = JacksonUtils.parse(o.getFieldDictJson(), JsonNode.class);
                        if (dictJson.get(v) != null) {
                            String realValue = dictJson.get(v).asText();
                            attrItem.setRealValue(realValue);
                        } else {
                            attrItem.setRealValue(v);
                        }
                    }
                } else if (DeviceDynamicAttrConstants.FieldTypeEnum.BOOL.getType().equals(o.getFieldType())) {
                    attrItem.setRealValue(SystemConstants.YES.toString().equals(v) ? SystemConstants.YES_CHINESE : SystemConstants.NO_CHINESE);
                } else {
                    attrItem.setRealValue(v);
                }
            }
            return attrItem;
        }).collect(Collectors.toList());
        deviceInfoVo.setDynamicAttrInfo(attrInfo);

        return Response.<DeviceDto>ok().wrap(deviceInfoVo);
    }

    /**
     * 保存
     */
    @PostMapping("save")
    @RequirePermissions(values = "device:edit")
    @Operation(summary = "保存单条设备记录")
    public Response<Object> save(@RequestBody @Validated DeviceDto deviceDto) {

        //填充基础数据
        fillSaveCommonData(deviceDto);
        DeviceDto oldDto = deviceService.selectByUniqueId(deviceDto.getUniqueId(), SessionHolder.getSysUser().getTenantId());
        if (oldDto != null) {
            return Response.error("该编码设备已存在");
        }
        oldDto = deviceService.selectCacheByImei(deviceDto.getImei(), SessionHolder.getSysUser().getTenantId());
        if (oldDto != null) {
            return Response.error("该IMEI设备已存在");
        }

        Response<Object> resp = checkExpandAttr(deviceDto.getDeviceCategoryId(), JacksonUtils.parse(deviceDto.getExtraAttr(), new TypeReference<HashMap<String, Object>>() {
        }));
        if (!resp.isSuccess()) {
            return resp;
        }

        // 默认为顶级设备
        deviceDto.setParentId(SystemConstants.TREE_DEFAULT_PARENT_ID);
        Long id = deviceService.save(deviceDto);


        setCustomRule(deviceDto, id);

        return Response.ok();
    }

    private void setCustomRule(DeviceDto deviceDto, Long deviceId) {
        // 先删除自定义规则
        alarmRuleDeviceConditionService.deleteByDeviceId(deviceId);
        if (SystemConstants.YES.equals(deviceDto.getCustomRule())) {
            if (deviceDto.getRuleList() != null) {
                for (AlarmRuleDto alarmRuleDto : deviceDto.getRuleList()) {
                    //其他租户
                    AlarmRuleDto dbValue = alarmRuleService.selectById(alarmRuleDto.getId());
                    //以下为其他租户可以修改的地方
                    dbValue.setStatus(alarmRuleDto.getStatus());
                    dbValue.setName(alarmRuleDto.getName());
                    dbValue.setAlarmConditionList(alarmRuleDto.getAlarmConditionList());


                    if (alarmRuleDto.getAlarmConditionList() != null) {
                        alarmRuleDto.getAlarmConditionList().forEach(v -> v.setCondition(HtmlUtils.decode(v.getCondition())));
                        for (AlarmRuleConditionDto alarmRuleConditionDto : alarmRuleDto.getAlarmConditionList()) {
                            Long deviceColumnId = alarmRuleConditionDto.getDeviceColumnId();
                            if (deviceColumnId != null) {
                                DeviceColumnDto deviceColumnDto = deviceColumnService.selectById(deviceColumnId);
                                if (deviceColumnDto != null) {
                                    alarmRuleConditionDto.setDeviceColumnEntityName(deviceColumnDto.getEntityName());
                                    alarmRuleConditionDto.setDeviceColumnCnName(deviceColumnDto.getCnName());
                                }
                            }
                        }
                    }


                    AlarmRuleDeviceConditionDto alarmRuleDeviceConditionDto = new AlarmRuleDeviceConditionDto();
                    alarmRuleDeviceConditionDto.setDeviceId(deviceId);
                    alarmRuleDeviceConditionDto.setTenantId(SessionHolder.getSysUser().getTenantId());
                    alarmRuleDeviceConditionDto.setRuleId(dbValue.getId());
                    alarmRuleDeviceConditionDto.setAlarmRuleConditionJson(JacksonUtils.toJsonString(dbValue));
                    alarmRuleDeviceConditionService.save(alarmRuleDeviceConditionDto);
                }
            }
        }
    }

    /**
     * 修改
     */
    @PostMapping("update")
    @RequirePermissions(values = "device:edit")
    @Operation(summary = "修改单条设备记录")
    public Response<Object> update(@RequestBody @Validated DeviceDto deviceDto) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(deviceDto.getId()));
        if (deviceService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        DeviceDto oldDto = deviceService.selectByUniqueId(deviceDto.getUniqueId(), SessionHolder.getSysUser().getTenantId());
        if (oldDto != null && !oldDto.getId().equals(deviceDto.getId())) {
            return Response.error("该编码设备已存在");
        }
        oldDto = deviceService.selectCacheByImei(deviceDto.getImei(), SessionHolder.getSysUser().getTenantId());
        if (oldDto != null && !oldDto.getId().equals(deviceDto.getId())) {
            return Response.error("该IMEI设备已存在");
        }
        Response<Object> resp = checkExpandAttr(deviceDto.getDeviceCategoryId(), JacksonUtils.parse(deviceDto.getExtraAttr(), new TypeReference<HashMap<String, Object>>() {
        }));
        if (!resp.isSuccess()) {
            return resp;
        }


        //填充基础数据
        fillEditCommonData(deviceDto);

        deviceDto.setParentId(null);
        deviceService.updateById(deviceDto);

        setCustomRule(deviceDto, deviceDto.getId());

        return Response.ok();
    }

    /**
     * 删除
     */
    @PostMapping("delete")
    @RequirePermissions(values = "device:delete")
    @Operation(summary = "批量删除设备记录")
    public Response<Object> delete(@RequestBody Long[] ids) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        for (Long id : ids) {

            params.remove(SystemConstants.ENTITY_ID_FLAG);
            params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

            if (deviceService.queryTotal(params) <= 0) {
                return Response.error(SystemConstants.ILLEGAL_MSG);
            }

            List<DeviceDto> children = deviceService.queryByParent(id);
            if (CollectionUtils.isNotEmpty(children)) {
                return Response.error("删除的设备存在子设备，请先删除子设备");
            }
        }

        deviceService.deleteBatch(ids);

        return Response.ok();
    }
}
